package com.zenchn.controller;

import com.zenchn.annotation.OperLog;
import com.zenchn.entity.FileMeta;
import com.zenchn.entity.HttpDataResult;
import com.zenchn.enums.OperLogActionEnum;
import com.zenchn.util.OtherUtils;
import com.zenchn.utils.CommonUtils;
import com.zenchn.utils.SizeConverter;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 * 临时文件(上传、删除) 模块控制器
 *
 * @author dingxinfa
 * @date 2020-04-20
 **/

@RestController
@RequestMapping(value = "tempFile")
@Api(value = "临时文件(上传、删除)模块控制器", tags = "通用-临时文件")
@RequiresAuthentication
public class TempFileController {


    private final String MODULE = "通用模块";
    /***
     * 文件保存临时目录
     */
    @Value("${custom.file.temp.path}")
    private String tmpPath;

    /***
     * 临时文件访问url
     */
    @Value("${custom.file.temp.url}")
    private String tmpUrl;

    /**
     * 上传单个文件
     *
     * @param request
     * @param response
     * @return
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.UPLOAD, detail = "上传单个文件")
    @ApiOperation(value = "上传单个文件", notes = "上传单个文件")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "isUnique", value = "是否唯一"),
            @ApiImplicitParam(dataType = "String", name = "fileSet", value = "文件归档集合", required = true),
            @ApiImplicitParam(dataType = "MultipartFile", name = "file", value = "上传文件", required = true)
    })
    @PostMapping(value = "/upload")
    public ResponseEntity<HttpDataResult<FileMeta>> upload(
            @RequestParam(value = "isUnique",required = false,defaultValue = "false") Boolean isUnique,
            @RequestParam(value = "fileSet") String fileSet,
            @RequestParam("file") MultipartFile multipartFile,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpDataResult<FileMeta> result = new HttpDataResult<FileMeta>(request.getRequestURI());

        // 获取session中保存的临时文件信息
        LinkedList<FileMeta> sessionFileMetaList = new LinkedList<FileMeta>();
        if (request.getSession().getAttribute(fileSet) != null) {
            if (isUnique) {
                request.getSession().removeAttribute(fileSet);
            } else {
                sessionFileMetaList = (LinkedList<FileMeta>) request.getSession().getAttribute(fileSet);
            }
        }
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
        String cDate = formatter.format(new Date());

        File filePath = new File(tmpPath + "//" + cDate);
        // 创建目录
        if (!filePath.exists()) {
            filePath.mkdirs();// 目录不存在的情况下，创建目录。
        }

        if (null != multipartFile) {
            //获取文件原名称
            String originalFilename =multipartFile.getOriginalFilename();

            String uuid = CommonUtils.randomUUID();
            assert originalFilename != null;
            String suffixName=originalFilename.substring(originalFilename.lastIndexOf('.')).toLowerCase();
            String saveFileName = uuid + suffixName;

            FileMeta fileMeta = new FileMeta();
            fileMeta.setFileName(originalFilename);
            fileMeta.setFileSize(SizeConverter.convertBytes(multipartFile.getSize(), true));

            fileMeta.setFileType(multipartFile.getContentType());
            fileMeta.setUuid(uuid);
            fileMeta.setSaveFilePath(formatter.format(new Date()) + "//"
                    + saveFileName);


            FileCopyUtils.copy(multipartFile.getBytes(), new FileOutputStream(tmpPath
                    + "//" + cDate + "//" + saveFileName));

            if (Objects.requireNonNull(multipartFile.getContentType()).contains("image")) {
                fileMeta.setThumbnailUrl(tmpUrl + cDate + "/" + saveFileName);
            } else {
                fileMeta.setThumbnailUrl(request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath() + "/" + OtherUtils.fileTypeJudge(suffixName));
            }




            fileMeta.setFileUrl(tmpUrl + cDate + "/" + saveFileName);
            fileMeta.setDeleteUrl("tempFile/delete/" + fileSet + "/" + uuid);

            sessionFileMetaList.add(fileMeta);

            result.setData(fileMeta);
        }
        // 将临时文件信息 保存到session 中
        request.getSession().setAttribute(fileSet, sessionFileMetaList);

        result.setMessage("OK");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }

    /**
     * 上传 多个文件
     *
     * @param request
     * @param response
     * @return
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.UPLOAD, detail = "上传多个文件")
    @ApiOperation(value = "上传多个文件", notes = "上传多个文件")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "fileSet", value = "文件归档集合", required = true),
            @ApiImplicitParam(dataType = "MultipartFile[]", name = "files", value = "上传文件数组")
    })
    @PostMapping(value = "/uploadList")
    public ResponseEntity<HttpDataResult<List<FileMeta>>> uploadList(
            @RequestParam("fileSet") String fileSet,
            @RequestParam("files") MultipartFile[] multipartFiles,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpDataResult<List<FileMeta>> result = new HttpDataResult<List<FileMeta>>(request.getRequestURI());

        // 获取session中保存的临时文件信息
        LinkedList<FileMeta> sessionFileMetaList = new LinkedList<>();
        if (request.getSession().getAttribute(fileSet) != null) {
            sessionFileMetaList = (LinkedList<FileMeta>) request.getSession().getAttribute(fileSet);
        }

        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
        String cDate = formatter.format(new Date());

        File filePath = new File(tmpPath + "//" + cDate);
        // 创建目录
        if (!filePath.exists()) {
            // 目录不存在的情况下，创建目录。
            filePath.mkdirs();
        }


        if (null != multipartFiles && multipartFiles.length > 0) {

            List<FileMeta> resultData = new ArrayList<>();
            for (MultipartFile multipartFile : multipartFiles) {
                //获取文件原名称
                String originalFilename = multipartFile.getOriginalFilename();

                String uuid = CommonUtils.randomUUID();
                assert originalFilename != null;

                String suffixName = originalFilename.substring(originalFilename.lastIndexOf('.')).toLowerCase();
                String saveFileName = uuid + suffixName;
                FileMeta fileMeta = new FileMeta();
                fileMeta.setFileName(originalFilename);
                fileMeta.setFileSize(SizeConverter.convertBytes(multipartFile.getSize(), true));

                fileMeta.setFileType(multipartFile.getContentType());
                fileMeta.setUuid(uuid);
                fileMeta.setSaveFilePath(formatter.format(new Date()) + "//"
                        + saveFileName);


                FileCopyUtils.copy(multipartFile.getBytes(), new FileOutputStream(tmpPath
                        + "//" + cDate + "//" + saveFileName));

                if (Objects.requireNonNull(multipartFile.getContentType()).contains("image")) {
                    fileMeta.setThumbnailUrl(tmpUrl + cDate + "/" + saveFileName);
                } else {
                    fileMeta.setThumbnailUrl(request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath() + "/" + OtherUtils.fileTypeJudge(suffixName));
                }

                fileMeta.setFileUrl(tmpUrl + cDate + "/" + saveFileName);
                fileMeta.setDeleteUrl("tempFile/delete/" + fileSet + "/" + uuid);


                sessionFileMetaList.add(fileMeta);
                resultData.add(fileMeta);
            }
            result.setData(resultData);

        }
        // 将临时文件信息 保存到session 中
        request.getSession().setAttribute(fileSet, sessionFileMetaList);

        result.setMessage("OK");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }


    /***
     *  删除临时文件
     * @param fileSet
     * @param uuid
     * @param request
     * @param response
     * @return
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.DELETE, detail = "删除临时文件")
    @ApiOperation(value = "删除临时文件", notes = "删除临时文件")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "uuid", value = "文件唯一编号", required = true),
            @ApiImplicitParam(dataType = "String", name = "fileSet", value = "文件归档集合", required = true)
    })
    @DeleteMapping(value = "/delete/{fileSet}/{uuid}")
    public ResponseEntity<HttpDataResult<Boolean>> delete(
            @PathVariable("fileSet") String fileSet,
            @PathVariable("uuid") String uuid,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpDataResult<Boolean> result = new HttpDataResult<Boolean>(request.getRequestURI());

        List<FileMeta> fileMetaList = new ArrayList<>();
        if (request.getSession().getAttribute(fileSet) != null) {
            fileMetaList = (List<FileMeta>) request.getSession().getAttribute(fileSet);
        }

        int count= (int) fileMetaList.stream().filter(f -> uuid.equals(f.getUuid())).count();

        boolean status = count<=0;
        if (count>0) {
            Iterator<FileMeta> iterator = fileMetaList.iterator();
            while (iterator.hasNext()) {
                FileMeta fileMeta = iterator.next();
                if (fileMeta.getUuid().equals(uuid)) {
                    try {
                        File file = new File(tmpPath + "//" + fileMeta.getSaveFilePath());
                        if (file.isFile() && file.exists()) {
                            file.delete();
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    status = true;
                    iterator.remove();
                }
            }
        }

        // 将临时文件信息 保存到session 中
        if (fileMetaList.size() > 0) {
            request.getSession().setAttribute(fileSet, fileMetaList);
        } else if (request.getSession().getAttribute(fileSet) != null) {
            request.getSession().removeAttribute(fileSet);
        }


        result.setData(status);
        result.setMessage("OK");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }


    /***
     *  删除临时文件归档集合
     * @param fileSet
     * @param request
     * @param response
     * @return
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.DELETE, detail = "删除临时文件归档集合")
    @ApiOperation(value = "删除临时文件归档集合", notes = "删除临时文件归档集合")
    @ApiImplicitParam(dataType = "String", name = "fileSet", value = "文件归档集合名称", required = true)
    @DeleteMapping(value = "/deleteFileSet/{fileSet}")
    public ResponseEntity<HttpDataResult<Boolean>> deleteFileSet(
            @PathVariable("fileSet") String fileSet,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpDataResult<Boolean> result = new HttpDataResult<Boolean>(request.getRequestURI());

        if (request.getSession().getAttribute(fileSet) != null) {
            List<FileMeta>  fileMetaList = (List<FileMeta>) request.getSession().getAttribute(fileSet);
            request.getSession().removeAttribute(fileSet);


            fileMetaList.forEach(fileMeta->{
                try {
                    File file = new File(tmpPath + "//" + fileMeta.getSaveFilePath());
                    if (file.isFile() && file.exists()) {
                        file.delete();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }

        result.setData(true);
        result.setMessage("OK");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }

}
